package com.sjf.day02.linkedlist;

/**
 * 双向链表Demo
 *
 * @author <huangtang>
 * @since 2021/12/20 15:08
 **/
public class DoubleLinkedListDemo {

    public static void main(String[] args) {
        DoubleLinkedList doubleList = new DoubleLinkedList();
        HeroNode2 node1 = new HeroNode2(1001, "a", "A");
        HeroNode2 node2 = new HeroNode2(1002, "b", "B");
        HeroNode2 node3 = new HeroNode2(1003, "c", "C");
        HeroNode2 node4 = new HeroNode2(1004, "d", "D");

        doubleList.add(node1);
        doubleList.add(node4);
        doubleList.add(node2);
        doubleList.addByNo(node3);

        doubleList.list();

        //doubleList.updateNodeByNo(new HeroNode2(1003,"ff","FF"));
        //System.out.println("修改后");
        //doubleList.deleteByNo(1002);

        //doubleList.list();
    }

}

/**
 * 定义一个双向链表
 */
class DoubleLinkedList{
    //先初始化一个头节点，遍历需要
    private HeroNode2 head = new HeroNode2(0,"","");

    /**
     * 遍历双向链表
     */
    public void list(){
        HeroNode2 temp = head.next;
        if(temp.next==null){
            System.out.println("链表为空");
            return;
        }
        while(temp!=null) {
            System.out.println(temp);
            temp = temp.next;
        }
    }

    /**
     * 添加节点到双向链表尾部
     */
    public void add(HeroNode2 heroNode){
        HeroNode2 temp = head;
        while(temp.next!=null){
            //循环遍历到最后一个节点
            temp = temp.next;
        }
        temp.next = heroNode;
        heroNode.prev = temp;
    }

    /**
     * 根据排序添加到链表指定位置
     */
    public void addByNo(HeroNode2 heroNode){
        //头节点遍历，遍历到no小于temp节点的后一个节点
        //进行插入，断掉前后节点的连接，将前节点的next指向插入节点，否则判断是否存在重复节点
        //插入节点的next指向后一个节点
        HeroNode2 temp = head;
        boolean flag = false; //判断是否存在相同节点
        while(true){
            //如果遍历到尾部直接退出循环
            if(temp.next == null){
                break;
            }
            //找到了插入的位置
            if(heroNode.no < temp.next.no){
                break;
            }else if(temp.next.no == heroNode.no){
                //说明添加的节点存在
                flag = true;
                break;
            }
            //没到尾部，没找到插入的位置，没有找到相同的节点，则继续向后遍历
            temp = temp.next;//向后遍历
        }
        if(flag){
            System.out.println(heroNode.no+"\t该节点已存在");
        }else{
            //如果没有出现相同的节点，则直接插入
                //temp.next.prev = heroNode;
                //heroNode.next = temp.next;
                //temp.next = heroNode;
                //heroNode.prev = temp;
                heroNode.next = temp.next;
                temp.next.prev=heroNode;
                temp.next=heroNode;
                heroNode.prev=temp;
        }
    }

    /**
     * 修改节点信息
     * @param heroNode
     */
    public void updateNodeByNo(HeroNode2 heroNode){
        if(isEmpty(head)){
            //判断是否为空链表
            System.out.println("链表为空");
            return;
        }
        //遍历链表找到需要修改的节点
        HeroNode2 temp = head;
        while(true){
            if(temp.next == null){
                //节点到达尾部
                System.out.println("未找到需要修改的节点");
                break;
            }
            //找到需要修改的节点
            if(temp.next.no == heroNode.no){
                //先删除当前节点，再插入修改后的节点
                //deleteByNo(temp.next.no);
                //addByNo(heroNode);
                temp.next.name = heroNode.name;
                temp.next.nickname = heroNode.nickname;
                //heroNode.prev = temp;
                //heroNode.next = temp.next.next;
            }
            temp = temp.next;
        }
    }

    /**
     * 从双向链表中删除节点
     * @param n
     */
    public void deleteByNo(int n){
        if(head.next==null) {
            System.out.println("当前链表为空，无法删除");
            return;
        }
        //遍历链表，对比no，如果找到
        //temp节点的next指向删除节点的下一个节点-- temp.next = temp.next.next;
        HeroNode2 temp = head.next;
        boolean flag = false;
        while(true){
            if(temp == null){
                //说明到达尾部
                break;
            }
            if(temp.no==n){
                //找到要删除的节点
                if(temp.next!=null){
                    //如果删除的节点不是最后一个节点
                    temp.prev.next = temp.next;
                    temp.next.prev = temp.prev;
                }else{
                    //删除的是最后一个节点
                    temp.prev.next=null;
                    temp.prev=null;
                }
                flag = true;
                break;
            }
            temp = temp.next; //向后遍历
        }
        if(!flag) System.out.println("未找到要删除的节点序号:\t"+ n);
    }


    public boolean isEmpty(HeroNode2 head){
        return head.next == null;
    }

}

/**
 * 定义一个HeroNode，每个HeroNode就是一个节点
 */
class HeroNode2{
    public int no;
    public String name;
    public String nickname;
    public HeroNode2 prev;//指向前一个节点
    public HeroNode2 next;//指向下一个节点

    public HeroNode2(int no, String name, String nickname) {
        this.no = no;
        this.name = name;
        this.nickname = nickname;
    }

    @Override
    public String toString() {
        return "HeroNode2{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickname='" + nickname + '\'' +
                '}';
    }
}
